<?php
namespace app\common\query;
use think\Db;
use app\common\model\Action as ActionModel;

class Action
{
	// 错误提示
	private $error='';
	// 消息队列
	private $data=[];
	private $action_name = '';
	// 用户账户
	private $account=[];

	static $status = [
				0 => '未处理',
				3 => '处理中',
				1 => '处理成功',
				2 => '处理失败',
			];

	public function __construct($uid,$action_name){
		$this->action_name = $action_name;
		$this->model = new ActionModel;
		// 用户账户
		$this->account = $this->memberAccount($uid);
		// 消息队列
		$data = $this->model->where(['uid'=>$uid,'action_name'=>$action_name,'status'=>0])->order('create_time','ASC')->select();
		if($data){
			foreach($data as &$value):
				$value=$value->toArray();
			endforeach;
		}else{
			$data = [];
		}
		$this->data = $data;
	}

	public function getError(){
		return $this->error;
	}

	public function deal(){
		$action_name = $this->action_name;
		$dataList = $this->data;
		if(empty($dataList)){
			return true;
		}
		if(method_exists($this, $action_name)){
			foreach($dataList as $value):
				// 操作记录表名
				$tableName = 'operate_'.$action_name;
				$value['action_data'] = unserialize($value['action_data']);
				// 锁表
				$update = [
					'status'=>3,
				];
				$this->model->save($update,['id'=>$value['id']]);
				// 更新状态
				Db::name($tableName)->where(['id'=>$value['operate_id']])->update($update);
				// 处理
				$result = $this->$action_name($value);
				if(false===$result){
					// 失败
					$update = [
						'status' => 2,
						'remark' => $this->error,
					];
					$this->model->save($update,['id'=>$value['id']]);
				}else{
					// 成功
					$update = [
						'status' => 1,
						'remark' => '交易成功',
					];
					$this->model->delete($value['id']);
				}
				// 更新操作记录表
				//$classname = 'Operate'.ucfirst($action_name);
				Db::name($tableName)->where(['id'=>$value['operate_id']])->update($update);
			endforeach;
		}else{
			$this->error='方法不存在';
			return false;
		}
	}

	/**
	 * 处理转账
	 * @return [type] [description]
	 */
	public function transfer($data){
		
		$operateId = $data['operate_id'];

		$actionData = $data['action_data'];

		$uid = $actionData['uid'];
		$targetUid = $actionData['target'];
		$coinId = $actionData['coin_id'];
		$amount = $actionData['amount'];
		$message = $actionData['message'];

		$memberModel = new \app\common\model\Member;
		$memberCoinModel = new \app\common\model\MemberCoin;
		$memberCoinRecordModel = new \app\common\model\MemberCoinRecord;

		// 获取转账配置
		$configData = model('coin_config')::coinConfigByType(__FUNCTION__);
		// 转账货币类型是否存在于设置中
		if(!in_array($coinId,array_column($configData, 'coin_id'))){
			$this->error='该货币类型不允许转账';
			return false;
		}
		// 获取当前货币转账配置
		$config = array_combine(array_column($configData,'coin_id'), $configData)[$coinId];
		// 转账金额计算
		$final_amount = $amount*$config['config']/100;
		// 余额判断
		$beforeAmount = $this->account[$coinId]['amount'];
		if($beforeAmount-$amount<0){
			$this->error='操作失败，账户'.$config['coin_name'].'不足';
			return false;
		}
		$memberModel->startTrans();
		try{
			// 扣款
			$memberCoinModel -> where(['uid'=>$uid,'coin_id'=>$coinId]) -> setDec('amount',$amount);
			$this->account = $this->memberAccount($uid);
			// 扣款后对应货币余额
			$afterAmount = $this->account[$coinId]['amount'];
			// 资金变动记录
			$record[] = [
				'operate_id' => $operateId,
				'uid' => $uid,
				'coin_id' => $config['coin_id'],
				'amount' => $amount,
				'operate' => __FUNCTION__,
				'before_amount' => $beforeAmount,
				'after_amount' => $afterAmount,
				'message' => $message,
				'remark' => '给【'.$targetUid.'】转账'.$amount.'【'.$config['coin_name'].'】',
				'flag' => 'dec'
			];
			if($afterAmount<0||($afterAmount+$amount)!=$beforeAmount){
				// 如果剩余资金小于0或者数据错误
				exception('账户'.$uid.'数据异常');
				// $memberModel->where(['id'=>$uid])->update(['status'=>4]);
				// return false;
			}

			// 入账前，目标账户余额
			$beforeAmountTarget = $memberCoinModel -> where(['uid'=>$targetUid,'coin_id'=>$config['coin_id']]) -> value('amount');
			// 入账
			$memberCoinModel -> where(['uid'=>$targetUid,'coin_id'=>$config['coin_id']]) -> setInc('amount',$final_amount);
			// 入账后收款账户对应货币余额
			$afterAmountTarget = $memberCoinModel -> where(['uid'=>$targetUid,'coin_id'=>$config['coin_id']]) -> value('amount');
			// 对方资金变动记录
			$record[] = [
				'operate_id' => $operateId,
				'uid' => $targetUid,
				'coin_id' => $config['coin_id'],
				'amount' => $final_amount,
				'operate' => __FUNCTION__,
				'before_amount' => $beforeAmountTarget,
				'after_amount' => $afterAmountTarget,
				'message' => $message,
				'remark' => '【'.$uid.'】转入'.$amount.'【'.$config['coin_name'].'】（税后'.$final_amount.'）',
				'flag' => 'inc',
			];
			$memberCoinRecordModel -> saveAll($record);

			$memberModel->commit();
		}catch(\Exception $e){
			$memberModel->rollback();
			$this->error = $e->getMassage();
			return false;
		}

		return true;

	}

	/**
	 * 货币转换处理
	 * @return [type] [description]
	 */
	public function convert($data){
		$operateId = $data['operate_id'];
		$actionData = $data['action_data'];

		$uid = $actionData['uid'];
		$convert_coin_id = $actionData['convert_coin_id'];
		$coinId = $actionData['coin_id'];
		$amount = $actionData['amount'];

		$memberCoinModel = new \app\common\model\MemberCoin;
		$memberCoinRecordModel = new \app\common\model\MemberCoinRecord;

		// 获得配置
		$configData = model('coin_config')::convertCoinConfig();
		if(!isset($configData[$coinId])){
			$this->error='该货币类型不允许被转换';
			return false;
		}
		// 该货币的转换配置
		$convertConfig = $configData[$coinId];
		$convertConfigTarget = $convertConfig['target'];
		$convertConfigTarget = array_combine(array_column($convertConfigTarget,'convert_coin_id'),$convertConfigTarget);
		if(!isset($convertConfigTarget[$convert_coin_id])){
			$this->error=$convertConfig['coin_name'].'不允许转成所选货币类型';
			return false;
		}
		// 原货币转目标货币配置
		$config = $convertConfigTarget[$convert_coin_id];
		// 转换金额计算
		$final_amount = $amount*$config['config']/100;
		// 余额判断
		$beforeAmount = $this->account[$coinId]['amount'];
		if($beforeAmount-$amount<0){
			$this->error='操作失败，账户'.$config['coin_name'].'不足';
			return false;
		}

		$memberCoinModel->startTrans();
		try{
			$memberCoinModel -> where(['uid'=>$uid,'coin_id'=>$coinId]) -> setDec('amount',$amount);
			$this->account = $this->memberAccount($uid);
			// 扣款后对应货币余额
			$afterAmount = $this->account[$coinId]['amount'];

			// 资金变动记录
			$record[] = [
				'operate_id' => $operateId,
				'uid' => $uid,
				'coin_id' => $coinId,
				'amount' => $amount,
				'operate' => __FUNCTION__,
				'before_amount' => $beforeAmount,
				'after_amount' => $afterAmount,
				'remark' => '将'.$amount.'【'.$config['coin_name'].'】转成'.$final_amount.'【'.$config['convert_coin_name'].'】',
				'flag' => 'dec'
			];

			// 入账前，目标货币账户余额
			$beforeAmountTarget = $memberCoinModel -> where(['uid'=>$uid,'coin_id'=>$config['convert_coin_id']]) -> value('amount');
			// 入账
			$memberCoinModel -> where(['uid'=>$uid,'coin_id'=>$config['convert_coin_id']]) -> setInc('amount',$final_amount);
			// 入账后，目标货币余额
			$this->account = $this->memberAccount($uid);
			$afterAmountTarget = $this->account[$config['convert_coin_id']]['amount'];
			// 资金变动记录
			$record[] = [
				'operate_id' => $operateId,
				'uid' => $uid,
				'coin_id' => $config['convert_coin_id'],
				'amount' => $final_amount,
				'operate' => __FUNCTION__,
				'before_amount' => $beforeAmountTarget,
				'after_amount' => $afterAmountTarget,
				'remark' => '将'.$amount.'【'.$config['coin_name'].'】转成'.$final_amount.'【'.$config['convert_coin_name'].'】',
				'flag' => 'inc',
			];
			$memberCoinRecordModel -> saveAll($record);

			$memberCoinModel->commit();
		}catch(\Exception $e){
			$memberCoinModel->rollback();
			$this->error = $e->getMassage();
			return false;
		}
		return true;
	}

	private function memberAccount($uid){
		$model = model('member_coin');
		$memberAccount = $model -> where(['uid'=>$uid])->select();
		foreach($memberAccount as &$account):
			$account=$account->toArray();
		endforeach;
		return array_combine(array_column($memberAccount,'coin_id'),$memberAccount);
	}

}